package cn.ryh.netty.bio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * BIO 示例
 *
 * @author Raoyh
 * @Description
 * @create 2022-09-08 15:57
 */
@Slf4j
public class BioServer {
    /**
     * 测试方法：使用cmd 命令 telnet 127.0.0.1 6666 然后 按CTRL+ ] 键 输入 send 消息内容 回车即可
     * 观察打印内容，每个CMD命令的线程名都是不一样的
     * @param args
     */
    public static void main(String[] args)  {
        // 线程池机制
        // 1、创建一个线程池
        // 2、如果有客户端连接就创建一个线程与之通讯
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 25, 10L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                new ThreadFactory() {
                    private AtomicInteger i = new AtomicInteger(0);

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread = new Thread(r);
                        thread.setName("线程" + i.getAndDecrement() + "号");
                        return thread;
                    }
                },
                new ThreadPoolExecutor.AbortPolicy());
        try (ServerSocket serverSocket = new ServerSocket(6666)) {
            while (true) {
                // 监听，等待客户端连接
                final Socket socket = serverSocket.accept();
                log.info("有一个客户端连接进来了");
                // 创建一个线程与连接进来的客户端通讯
                threadPool.execute(() -> {
                    handler(socket);
                });
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void handler(Socket socket) {
        String name = Thread.currentThread().getName();
        byte[] buffer = new byte[1024];
        // 通过socket 获取输入流
        try (InputStream inputStream = socket.getInputStream();) {
            // 循环读取客户端发送的数据
            int read;
            while ((read = inputStream.read(buffer)) != -1) {
                log.info("{},收到客户端传输的数据:{}", name,new String(buffer, 0, read));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
